package fr.poy.mygluco.client.ui;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.EventListener;
import java.util.Iterator;
import java.util.List;

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FormEvent;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.LoadListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.util.DateWrapper;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.FileUploadField;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.LabelField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.extjs.gxt.ui.client.widget.form.TimeField;
import com.extjs.gxt.ui.client.widget.form.FormPanel.Encoding;
import com.extjs.gxt.ui.client.widget.form.FormPanel.Method;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.GridViewConfig;
import com.extjs.gxt.ui.client.widget.grid.RowEditor;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;

import fr.poy.mygluco.client.App;
import fr.poy.mygluco.client.gxt.AppListener;
import fr.poy.mygluco.client.gxt.AppLogsAsyncCallback;
import fr.poy.mygluco.model.AppLogs;
import fr.poy.mygluco.model.Record;

public final class UploadData extends Window{

	private static UploadData instance = new UploadData();
	private final ContentPanel g ;
	private ListLoader<ListLoadResult<ModelData>> loader ;
	private ArrayList<EventListener> listeners = new ArrayList<EventListener>();

	
	public static UploadData getInstance() {
		return instance;
	}

	private UploadData() {

		this.setModal(true);
		this.setBlinkModal(true);
		this.setHeading(App.getMessages().importDialogTitle() );
		this.setIconStyle("toolbar-import");
		this.setSize(700, 400);
		this.setLayout(new BorderLayout());
		
		// ------------------------------------------
		final FormPanel panel = new FormPanel();
		panel.setHeaderVisible(false); 
		panel.setHideLabels(true);
		panel.setFrame(true);  
		
		panel.setEncoding(Encoding.MULTIPART);
		panel.setMethod(Method.POST);
		panel.setAction(GWT.getModuleBaseURL() +"upload");
		panel.addListener( Events.BeforeSubmit, new Listener<FormEvent>() {
	        public void handleEvent(final FormEvent be) {
	        	g.setHeading(App.getMessages().importUploadFile());
	        }
	    }); 
		panel.addListener( Events.Submit, new Listener<FormEvent>() {
	        public void handleEvent(final FormEvent be) {
	        	g.setHeading(App.getMessages().importUploadProcess());
	        	loader.load();
	        }
	    });  
		//-----------------------------------
		
		LabelField a = new LabelField(App.getMessages().importChapo());  
		panel.add(a, new FormData("100%"));  
		//------------------  
		LayoutContainer main = new LayoutContainer();
		main.setLayout(new ColumnLayout());
		//-----------
		LayoutContainer left = new LayoutContainer();
		left.setStyleAttribute("paddingTop", "10px");
		FormLayout layout = new FormLayout(); 
		left.setLayout(layout);
		 
		final FileUploadField file = new FileUploadField(); 
		file.setHideLabel(true);
		file.setName("file");   
		file.setAllowBlank(false);  
		left.add(file); 
		 
		//-----------
		LayoutContainer right = new LayoutContainer();
		right.setStyleAttribute("paddingTop", "10px");
		layout = new FormLayout(); 
		right.setLayout(layout);

		Button btn = new Button(App.getMessages().importUploadButton());
		btn.addSelectionListener(new SelectionListener<ButtonEvent>() { 
			public void componentSelected(ButtonEvent ce) {
				if (!panel.isValid())  return;
				panel.submit();//TODO http status ?
			}
		}); 
		right.add(btn, new FormData("40%")); 
		 
		final LabelField lastImport = new LabelField(getLastImportDate());
		lastImport.setHideLabel(true);
		right.add(lastImport, new FormData("80%")); 
		
		//-----------
		main.add(left, new ColumnData(.4));
		main.add(right, new ColumnData(.6)); 
		panel.add(main); 
		this.add(panel,new BorderLayoutData(LayoutRegion.NORTH,100));
		
		
		//----------------------------
		g = new ContentPanel(new FitLayout()); 
		// proxy and reader  
		RpcProxy<List<Record>> proxy = new RpcProxy<List<Record>>() {  
			@Override  
			public void load(Object loadConfig, AsyncCallback<List<Record>> callback) {  
				App.getService().processImportFile(callback);  
			}  
		};  
		BeanModelReader reader = new BeanModelReader();   
		loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);  
		loader.addLoadListener(new LoadListener(){ 
			public void loaderLoad(LoadEvent le) { 
				g.setHeading(App.getMessages().importCheckData());
			} 
		});
		final ListStore<BeanModel> store = new ListStore<BeanModel>(loader);  
		
		//FIXME casse le tri par default !!!
//		store.setStoreSorter(new StoreSorter<BeanModel>(){ 
//			public int compare(Store<BeanModel> store, BeanModel m1, BeanModel m2, String property) { 
//				if("gxtTime".equals(property)){
//					Time t1 = ((Time)m1.get(property));
//					Time t2 = ((Time)m2.get(property));
//					return (t1.getHour()*60+t1.getMinutes()) -  (t2.getHour()*60+t2.getMinutes());
//				}else
//					return super.compare(store, m1, m2, property);
//			} 
//        });
		
		
		// column model
		List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
	    CheckBoxSelectionModel<BeanModel> sm = new CheckBoxSelectionModel<BeanModel>();   
	    columns.add(sm.getColumn());  
		
		ColumnConfig cc = new ColumnConfig("day", App.getMessages().recordLabelJour(), 60); 
		cc.setRenderer(new GridCellRenderer<ModelData>(){ 
			public Object render(ModelData model, String property
					, com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
					ListStore<ModelData> store, Grid<ModelData> grid) {
				return
				DateTimeFormat.getFormat(App.getUserProfile().getDayFormat()).format((Date) model.get("date"));
			}
			
		});
		columns.add(cc);
		
		cc = new ColumnConfig("date",App.getMessages().recordLabelDate() , 90);
		cc.setDateTimeFormat(DateTimeFormat.getFormat(App.getUserProfile().getDateFormat()));
		DateField dateField = new DateField();  
		dateField.getPropertyEditor().setFormat(DateTimeFormat.getFormat(App.getUserProfile().getDateFormat()/*+" "+App.getUserProfile().getTimeFormat()*/));
		cc.setEditor(new CellEditor(dateField) );  
		columns.add(cc);
		
		cc = new ColumnConfig("gxtTime",App.getMessages().recordLabelTime() , 65);
		//cc.setDateTimeFormat(DateTimeFormat.getFormat(App.getConstants().timeFormat()));
		cc.setRenderer(new GridCellRenderer<ModelData>(){ 
            public Object render(ModelData model, String property
                    , com.extjs.gxt.ui.client.widget.grid.ColumnData config, int rowIndex, int colIndex,
                    ListStore<ModelData> store, Grid<ModelData> grid) {
                return 
                 DateTimeFormat.getFormat(App.getUserProfile().getTimeFormat()).format(((Time)model.get(property)).getDate());
            }
        });
        TimeField timeField = new TimeField();  
        //timeField.setFormat(DateTimeFormat.getFormat(App.getConstants().timeFormat()));
        cc.setEditor(new CellEditor(timeField));
        columns.add(cc);

		
		cc = new ColumnConfig("bg",App.getMessages().recordLabelBg() , 50);
		cc.setAlignment(HorizontalAlignment.RIGHT); 
		NumberField nf = new NumberField();
		nf.setPropertyEditorType(Integer.class);
		nf.setAllowNegative(false);
		nf.setAllowBlank(false);
		nf.setAllowDecimals(false);
		cc.setEditor(new CellEditor(nf));  
		columns.add(cc); 
		
		//columns.add(new ColumnConfig("source",App.getMessages().recordLabelSource() , 50));
		//TODO autocomplete Combo
		cc = new ColumnConfig("flag",App.getMessages().recordLabelFlag() , 40);
		cc.setAlignment(HorizontalAlignment.CENTER);  
		cc.setEditor(new CellEditor(new TextField<String>()));  
		columns.add(cc);
		
		cc = new ColumnConfig("ins1",App.getMessages().recordLabelIns1() , 50);
		cc.setAlignment(HorizontalAlignment.RIGHT); 
		NumberField nfi = new NumberField();
		nfi.setPropertyEditorType(Integer.class);
		nfi.setAllowNegative(false); 
		nfi.setAllowDecimals(false);
		cc.setEditor(new CellEditor(nfi));  
		columns.add(cc); 
		 
		cc = new ColumnConfig("ins2",App.getMessages().recordLabelIns2() , 50);
		NumberField nfi2 = new NumberField();
		nfi2.setPropertyEditorType(Integer.class);
		nfi2.setAllowNegative(false); 
		nfi2.setAllowDecimals(false);
		cc.setAlignment(HorizontalAlignment.RIGHT);  
		cc.setEditor(new CellEditor(nfi2));  
		columns.add(cc); 
		
		cc = new ColumnConfig("ins3",App.getMessages().recordLabelIns3() , 50);
		cc.setAlignment(HorizontalAlignment.RIGHT);
		NumberField nfi3 = new NumberField();
		nfi3.setPropertyEditorType(Integer.class);
		nfi3.setAllowNegative(false); 
		nfi3.setAllowDecimals(false);
		cc.setEditor(new CellEditor(nfi3));  
		columns.add(cc); 
		
		
		//TODO autocomplete Combo
		cc = new ColumnConfig("event",App.getMessages().recordLabelEvent() , 100);
		cc.setEditor(new CellEditor(new TextField<String>())); 
		columns.add(cc);
		
		cc = new ColumnConfig("comment",App.getMessages().recordLabelComment() , 300);
		cc.setEditor(new CellEditor(new TextField<String>())); 
		columns.add(cc);
		
		ColumnModel cm = new ColumnModel(columns);

		final EditorGrid<BeanModel> grid = new EditorGrid<BeanModel>(store, cm); 
		grid.setLoadMask(true);
		grid.setBorders(false);
		grid.setAutoExpandColumn("comment"); 
	    grid.setSelectionModel(sm);
	    grid.addPlugin(sm);  
	    grid.getView().setViewConfig(new GridViewConfig(){ 
			public String getRowStyle(ModelData model, int rowIndex, ListStore<ModelData> ds) {
				if(model.get("id")!=null)
					return "grid-persitent-row";
				else return super.getRowStyle(model, rowIndex, ds);
			} 
	    });
  
		g.add(grid);
		this.add(g,new BorderLayoutData(LayoutRegion.CENTER ));
		
		this.addButton(new Button(App.getMessages().importButtonDel() ,new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				for (BeanModel b : grid.getSelectionModel().getSelectedItems()) {
					store.remove(b);
				}
			}
		}));
		  
		this.addButton(new Button(GXT.MESSAGES.messageBox_ok(),new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {  
				UploadData.this.hide();
//				for (com.extjs.gxt.ui.client.store.Record r : store.getModifiedRecords()) {
//					r.set("source", Record.SOURCE.METER_MANUAL);
//				}
				
				List<Record> l = new ArrayList<Record>(); 
				for (BeanModel m : store.getModels()) {
					Record r = (Record) m.getBean();
					if(r.getId()==null){ 
						l.add(r);
					}
				} 
				store.commitChanges();
				
				App.getService().persistRecords(l, new AppLogsAsyncCallback(){ 
					public void onSuccess(AppLogs o) { 
						super.onSuccess(o);
						onRecordListChange();
						store.removeAll(); 
						g.setHeading("");
						file.reset(); 
						App.getUserProfile().setLastImport(new Date());
						App.saveProfile(); 
						lastImport.setText(getLastImportDate());
					} 
				}); 
			}
		}) );
		
		this.addButton(new Button(App.getMessages().buttonReset() ,new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) { 
				store.rejectChanges();
			}
		}));
		
		this.addButton(new Button(GXT.MESSAGES.messageBox_cancel(),new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) { 
				UploadData.this.hide();
				store.removeAll(); 
				g.setHeading("");
				file.reset();
			}
		}));

	}

	public void addAppListener(AppListener listener) {
		listeners.add(listener);
	}

	public void removeAppListener(AppListener listener) {
		listeners.remove(listener);
	}

	public void onRecordListChange(){
		for (Iterator<EventListener> it = listeners.iterator(); it.hasNext();) {
			AppListener listener = (AppListener) it.next();
			listener.onRecordListChange();
		}
	}

	private String getLastImportDate(){
		return App.getUserProfile().getLastImport() == null ? "" 
				: App.getMessages()
					.importLastImport(
							DateTimeFormat.getFormat(
									App.getUserProfile().getDateFormat()+" "+App.getUserProfile().getTimeFormat()
									).format(App.getUserProfile().getLastImport()));  
	}

}
